﻿/**************************************************************
 *
 * 唯一标识：ae6be4be-c41d-4d36-946b-8a909f1f5fb9
 * 命名空间：System
 * 创建时间：2023/8/17 12:01:03
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using Sgr;

namespace System
{
    public static class DateTimeExtensions
    {
        /// <summary>
        /// 将 DateTime 转换为 ISO 8601 格式的字符串。
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static string ToIso8601String(this DateTime dateTime)
        {
            return dateTime.ToString("o"); // "o" 表示 ISO 8601 格式
        }

        /// <summary>
        /// 保证返回的时间为 UTC（Kind=Utc）。
        /// 默认：Local => 转换为 UTC；Unspecified => 仅补 Kind 不做换算。
        /// 可选：treatUnspecifiedAsLocal=true 时，Unspecified 按本地再转 UTC。
        /// 同时对超出边界的值按 Constant.Min/Max 限制。
        /// </summary>
        /// <param name="value">输入时间</param>
        /// <param name="treatUnspecifiedAsLocal">
        /// 是否将未指定 Kind 的时间视为 Local 后再换算为 UTC。
        /// false = 直接 SpecifyKind(UTC)；true = 当作本地时间再 ToUniversalTime()</param>
        /// <returns>Kind=Utc 的时间（已裁剪边界）</returns>
        public static DateTime EnsureUtc(this DateTime value, bool treatUnspecifiedAsLocal = false)
        {
            //if (value <= Constant.MinDateTime)
            //    return DateTime.SpecifyKind(Constant.MinDateTime, DateTimeKind.Utc);

            //if (value >= Constant.MaxDateTime)
            //    return DateTime.SpecifyKind(Constant.MaxDateTime, DateTimeKind.Utc);

            return value.Kind switch
            {
                DateTimeKind.Utc => value,
                DateTimeKind.Local => value.ToUniversalTime(),
                _ => treatUnspecifiedAsLocal
                        ? DateTime.SpecifyKind(value, DateTimeKind.Local).ToUniversalTime()
                        : DateTime.SpecifyKind(value, DateTimeKind.Utc)
            };
        }

        /// <summary>
        /// 可空版本：保证非空值为 UTC；空值直接返回 null。
        /// </summary>
        public static DateTime? EnsureUtc(this DateTime? value, bool treatUnspecifiedAsLocal = false)
            => value.HasValue ? value.Value.EnsureUtc(treatUnspecifiedAsLocal) : null;

        /// <summary>
        /// 将 DateTime 转换为 DateTimeOffset
        /// </summary>
        /// <param name="dateTime">要转换的 DateTime 值</param>
        /// <returns>转换后的 DateTimeOffset 值</returns>
        /// <exception cref="ArgumentOutOfRangeException">当日期超出有效范围时抛出</exception>
        /// <remarks>
        /// 转换规则：
        /// - Utc: 直接使用零时区偏移创建 DateTimeOffset
        /// - Local: 使用本地时区偏移创建 DateTimeOffset
        /// - Unspecified: 先转换为 UTC 再创建 DateTimeOffset
        /// </remarks>
        public static DateTimeOffset ToDateTimeOffset(this DateTime dateTime)
        {
            //// 边界检查
            //if (dateTime <= Constant.MinDateTime)
            //    return Constant.MinDateTime;

            //if (dateTime >= Constant.MaxDateTime)
            //    return Constant.MaxDateTime;

            return dateTime.Kind switch
            {
                // UTC 时间：直接使用 0 偏移
                DateTimeKind.Utc => new DateTimeOffset(dateTime, TimeSpan.Zero),

                // 本地时间：使用本地时区偏移
                DateTimeKind.Local => new DateTimeOffset(dateTime),

                // 未指定：转换为 UTC
                _ => new DateTimeOffset(dateTime.ToUniversalTime(), TimeSpan.Zero)
            };
        }

        /// <summary>
        /// 将 DateTime 转换为指定时区偏移的 DateTimeOffset
        /// </summary>
        /// <param name="dateTime">要转换的 DateTime 值</param>
        /// <param name="offset">目标时区偏移</param>
        /// <returns>转换后的 DateTimeOffset 值</returns>
        public static DateTimeOffset ToDateTimeOffset(this DateTime dateTime, TimeSpan offset)
        {
            // 边界检查
            if (dateTime <= Constant.MinDateTime)
                return Constant.MinDateTime;

            if (dateTime >= Constant.MaxDateTime)
                return Constant.MaxDateTime;

            // 如果是 UTC 或未指定，先转换为 UTC
            if (dateTime.Kind != DateTimeKind.Local)
                dateTime = dateTime.ToUniversalTime();

            // 创建指定偏移的 DateTimeOffset
            return new DateTimeOffset(dateTime.Add(offset), offset);
        }
    }
}